home *** CD-ROM | disk | FTP | other *** search
- /*
- * zbuf.c
- *
- * Add Z buffer support to Rayshade 4.0, by Mark W. Maimone (mwm@cs.cmu.edu)
- *
- * Rayshade is a rendering package by Craig Kolb, et al
- * Copyright (C) 1989, 1991, Craig E. Kolb
- * All rights reserved.
- *
- * This software may be freely copied, modified, and redistributed
- * provided that this copyright notice is preserved on all copies.
- *
- * You may not distribute this software, in whole or in part, as part of
- * any commercial product without the express consent of the authors.
- *
- * There is no warranty or other guarantee of fitness of this software
- * for any purpose. It is provided solely "as is".
- *
- * zbuf.c,v 4.1 1994/08/09 08:05:23 explorer Exp
- *
- * zbuf.c,v
- * Revision 4.1 1994/08/09 08:05:23 explorer
- * Bump version to 4.1
- *
- * Revision 1.1.1.1 1994/08/08 04:52:19 explorer
- * Initial import. This is a prerelease of 4.0.6enh3, or 4.1 possibly.
- *
- */
-
- #include "rayshade.h"
- #include "options.h"
- #include "zbuf.h"
- #include "viewing.h"
-
- typedef struct {
- char *s;
- int i;
- } PairT;
-
- RSZbuf zbuffer;
-
- /* Must set the proper window size before calling ZbufSetup() */
-
- void
- ZbufSetup()
- {
- int horiz = Screen.xsize;
- int vert = Screen.ysize;
- int i, j;
-
- if (Options.zbufname == (char *)NULL)
- return;
- if ((zbuffer.fzbuf = fopen (Options.zbufname, "w")) == NULL)
- RLerror(RL_PANIC, "Cannot open Z buffer file \"%s\".\n",
- Options.zbufname);
- zbuffer.array = (Float **) Malloc (vert * sizeof (Float *));
-
- /* Initialize all depths to Infinity */
-
- for (i = 0; i < vert; i++) {
- zbuffer.array[i] = (Float *) Malloc (horiz * sizeof (Float));
- for (j = 0; j < horiz; j++)
- zbuffer.array[i][j] = ZBUF_INF;
- } /* for */
- } /* ZbufSetup */
-
-
- /* ZbufAdd -- Some object in pixel (x,y) is distance dist from the
- eye. Add it to the Z buffer if it's nearer than all other objects seen
- so far. This simple-minded storage scheme relies on the anti-aliasing
- to sample the pixel at appropriate places. It also assumes you want
- the distance of the *nearest* object touching the pixel as the final
- distance measure. */
-
- void ZbufAdd (x, y, dist)
- Float x, y, dist;
- {
- int j = ((int) (x + 0.5)) - Screen.minx;
- int i = ((int) (y + 0.5)) - Screen.miny;
-
- if (zbuffer.array && i >= 0 && j >= 0 && i < Screen.ysize &&
- j < Screen.xsize)
- {
- Float before = zbuffer.array[i][j];
-
- if (before == ZBUF_INF || dist < before)
- zbuffer.array[i][j] = dist;
- }
- } /* ZbufAdd */
-
-
- /* ZbufPrint -- Write the Z buffer data to a file. Output format is
- determined by the filename, or by DEFAULT_ZBUF_TYPE. Three formats
- are available:
-
- HF -- Output is written in Heightfield format
- TXT -- After some opening comments, distances are written in
- ascii. Each line in the output file contains distances for
- the corresponding image line, separated by a single space.
- TXT3 -- After some opening comments, distances are
- output as a triple: pixel coordinate and distance (e.g.:
-
- 0 3 3.14146
-
- means at position (0,3) the depth is 3.13146. This is very
- space-inefficient, but is quite portable, and can be directly read by
- GNUplot for easy viewing.
-
- % rayshade -R 50 50 -z zbuf.dat Examples/balls.ray > balls.rle
- % gnuplot
- gnuplot> set term x11 [or whatever you're on]
- gnuplot> set sample 2500 [for a 50x50 image]
- gnuplot> set parametric [needed to plot 3D data]
- gnuplot> splot 'zbuf.dat' with lines
- [gives a nice height map grid]
- gnuplot> help set view [info on changing viewpoint]
- gnuplot> set view 45, 45 [a sample viewpoint]
- gnuplot> quit
-
- Warning! Distances are expected to always be positive, so background
- pixels are represented by a distance of ZBUF_INF (i.e., -1000). To get
- nice looking GNUplot output you should replace all -1's with the maximum
- distance. On UNIX:
-
- % rayshade -R 50 50 -z zbuf.dat Examples/planet.ray > balls.rle
- % awk 'BEGIN {max = -1} NF == 3 { if ($3 > max) max = $3} END \
- {print max}' < zbuf.dat [this gives you the max]
- 3.69359
- % sed s/-1000/3.69359/g < zbuf.dat | awk 'NF == 3 { print $1" "$2" -"$3 \
- ; next} {print}' > zbuf.plot [replace -1 with max, make all
- distances negative so the
- plot appears rightside up]
- % gnuplot
- .
- .
- gnuplot> set zrange [-3.7:0]
- gnuplot> splot 'zbuf.plot'
- */
-
- static PairT exts[] = {
- "hf", ZBUF_HF,
- "rle", ZBUF_RLE,
- "txt", ZBUF_TXT,
- "txt3", ZBUF_TXT3, /* silly suffix, for backward compatability */
- "etxt", ZBUF_TXT3,
- }; /* exts */
-
- void ZbufPrint ()
- {
- int type = ZsetOutputType (Options.zbufname);
- int len = Screen.xsize;
- int y;
- FILE *fp = zbuffer.fzbuf;
- char *filename = Options.zbufname;
-
- if (PrepareForOutput (type, fp, filename) == 0)
- return;
- #ifdef URT
- for (y = Screen.ysize-1; y >= 0; y--)
- #else
- for (y = 0; y < Screen.ysize; y++)
- #endif
- WriteRow (type, y + Screen.miny, fp, filename, zbuffer.array[y], len);
-
- NoMoreThisImage (type, fp, filename);
- } /* ZbufPrint */
-
- int PrepareForOutput (type, fp, filename)
- int type;
- FILE *fp;
- char *filename;
- {
- HEIGHTFIELD_SIZE i;
-
- if (fp == NULL) return 0;
-
- switch (type) {
- case ZBUF_HF:
- i = Screen.xsize;
- if (i < Screen.ysize) i = Screen.ysize;
- fwrite (&i, sizeof (HEIGHTFIELD_SIZE), 1, fp);
- zbuffer.pad = i - Screen.xsize;
- break;
- case ZBUF_RLE:
- fprintf (stderr, "Sorry, RLE output not available\n");
- return 0;
- case ZBUF_TXT:
- case ZBUF_TXT3:
- fprintf (fp, "# Rayshade Z-buffer output file for command:\n");
- fprintf (fp, "# ");
- ZwriteArgv (fp, zbuffer.argv);
- if (zbuffer.rayfile)
- fprintf (fp, "\n# Input RAY file: \"%s\"\n", zbuffer.rayfile);
- if (zbuffer.outfile)
- fprintf (fp, "# Output file: \"%s\"\n", zbuffer.outfile);
- fprintf (fp, "# Resolution for this rendering is %dx%d\n",
- Screen.xres, Screen.yres);
- fprintf (fp, "# window from (%d,%d) to (%d,%d)\n",
- Screen.minx, Screen.miny, Screen.maxx, Screen.maxy);
- break;
- default:
- fprintf (stderr, "Error! Unknown Z buffer type '%d'\n", type);
- return 0;
- } /* switch */
- return 1;
- } /* PrepareForOutput */
-
- WriteRow (type, y, fp, filename, row, len)
- int type, y;
- FILE *fp;
- char *filename;
- Float *row;
- int len;
- {
- int i;
- char *sep = "";
- static float *padding = NULL;
- static int pad_len = 0, vec_len = 0;
- static float *vec = NULL;
-
- switch (type) {
- case ZBUF_HF:
- if (vec_len < len) {
- if (vec) free (vec);
- vec_len = ((len+9) / 10) * 10;
- vec = (float *) malloc (sizeof (float) * vec_len);
- }
- for (i = 0; i < len; i++)
- vec[i] = (float) row[i];
- fwrite (vec, sizeof (float), len, fp);
- if (zbuffer.pad) {
- if (pad_len < zbuffer.pad) {
- if (padding) free (padding);
- pad_len = ((zbuffer.pad+9) / 10) * 10;
- padding = (float *) malloc (sizeof (float) * pad_len);
- for (i = 0; i < pad_len; i++) padding[i] = ZBUF_INF;
- } /* if */
- fwrite (padding, sizeof (float), zbuffer.pad, fp);
- }
- break;
- case ZBUF_TXT:
- for (i = 0; i < len; i++) {
- fprintf (fp, "%s%g", sep, row[i]);
- sep = " ";
- } /* for */
- fprintf (fp, "\n");
- break;
- case ZBUF_TXT3:
- for (i = 0; i < len; i++)
- fprintf (fp, "%d %d %g\n", i + Screen.minx, y, row[i]);
- fprintf (fp, "\n");
- break;
- default:
- fprintf (stderr, "*Invalid type %d in WriteRow\n", type);
- break;
- } /* switch */
- } /* WriteRow */
-
- NoMoreThisImage (type, fp, filename)
- int type;
- FILE *fp;
- char *filename;
- {
- if (type == ZBUF_HF)
- if (Screen.xsize > Screen.ysize) {
- int len = Screen.xsize - Screen.ysize;
- int i;
- float *padding = (float *) malloc (sizeof (float) * Screen.xsize);
-
- for (i = 0; i < Screen.xsize; i++)
- padding[i] = ZBUF_INF;
- while (len-- > 0)
- fwrite (padding, sizeof (float), Screen.xsize, fp);
- free (padding);
- } /* if */
- fclose (fp);
- zbuffer.fzbuf = NULL;
- } /* NoMoreThisImage */
-
- ZwriteArgv (fp, argv)
- FILE *fp;
- char **argv;
- {
- char *sep = "";
-
- if (fp == NULL || argv == NULL) return;
-
- while (*argv) {
- fprintf (fp, "%s%s", sep, *argv);
- sep = " ";
- argv++;
- }
- } /* ZwriteArgv */
-
- int ZsetOutputType (filename)
- char *filename;
- {
- int i, len;
- int type = DEFAULT_ZBUF_TYPE;
-
- if (filename != NULL) {
- len = strlen (filename);
- for (i = 0; i < sizeof (exts) / sizeof (PairT); i++)
- if (len >= strlen (exts[i].s) && strcmp (exts[i].s,
- filename + len - strlen (exts[i].s)) == 0) {
- type = exts[i].i;
- break;
- } /* if */
- } /* if */
-
- /* No RLE output yet */
-
- if (type == ZBUF_RLE) {
- fprintf (stderr,
- " (Z buffer not in available in RLE format yet, sorry)\n");
- type = DEFAULT_ZBUF_TYPE;
- } /* if */
-
- if (type) {
- fprintf (stderr, "Z buffer will be written in ");
- switch (type) {
- case ZBUF_HF: fprintf (stderr, "HEIGHTFIELD"); break;
- case ZBUF_TXT: fprintf (stderr, "TEXT"); break;
- case ZBUF_TXT3: fprintf (stderr, "EXPANDED TEXT"); break;
- case ZBUF_RLE: fprintf (stderr, "UTAH RASTER TOOLKIT"); break;
- default: fprintf (stderr, "UNKNOWN!!");
- type = 0; break;
- } /* switch */
- fprintf (stderr, " format to \"%s\"\n", Options.zbufname);
- } /* if */
- return type;
- } /* ZsetOutputType */
-
-
- #ifdef SDfl
-
- void ZbufPrint ()
- {
- FILE *fp = zbuffer.fzbuf;
- int minx = Screen.minx, maxx = Screen.maxx;
- int miny = Screen.miny, maxy = Screen.maxy;
- int horiz = Screen.xsize;
- int vert = Screen.ysize;
- int x, y;
-
- if (fp == NULL)
- return;
-
- fprintf (fp, "# Depth Map for Rayshade output file\n");
- if (zbuffer.rayfile)
- fprintf (fp, "# Input RAY file: \"%s\"\n", zbuffer.rayfile);
- if (zbuffer.outfile)
- fprintf (fp, "# Output file: \"%s\"\n", zbuffer.outfile);
- fprintf (fp, "# Resolution for this rendering is %dx%d\n",
- Screen.xres, Screen.yres);
- fprintf (fp, "# window from (%d,%d) to (%d,%d)\n",
- minx, miny, maxx, maxy);
- fprintf (fp, "# Screen X unit vector: (%g,%g,%g)\n",
- Screen.scrnx.x, Screen.scrnx.y, Screen.scrnx.z);
- fprintf (fp, "# Screen Y unit vector: (%g,%g,%g)\n",
- Screen.scrny.x, Screen.scrny.y, Screen.scrny.z);
-
- /* Would be nice to save command-line options too */
-
- for (x = 0; x < horiz; x++)
- {
- for (y = 0; y < vert; y++)
- fprintf (fp, "%d %d %g\n", x, y, zbuffer.array[x][y]);
-
- fprintf (fp, "\n");
-
- } /* for */
-
- fclose (fp);
- zbuffer.fzbuf = NULL;
-
- } /* ZbufPrint */
- #endif
-